#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
文件格式转换工具箱
支持多种文件格式的互相转换
"""

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import sys
import threading
from pathlib import Path

# 导入转换模块
from converters.document_converter import DocumentConverter
from converters.spreadsheet_converter import SpreadsheetConverter
from converters.image_converter import ImageConverter
from converters.other_converter import OtherConverter
from converters.markdown_converter import MarkdownConverter
from converters.archive_converter import ArchiveConverter
from converters.encoding_converter import EncodingConverter


class FileConverterApp:
    def __init__(self, root):
        self.root = root
        self.root.title("文件格式转换工具箱 v3.0.1")
        self.root.geometry("1000x900")
        self.root.resizable(True, True)

        # 初始化转换器
        self.doc_converter = DocumentConverter()
        self.sheet_converter = SpreadsheetConverter()
        self.img_converter = ImageConverter()
        self.other_converter = OtherConverter()
        self.md_converter = MarkdownConverter()
        self.archive_converter = ArchiveConverter()
        self.encoding_converter = EncodingConverter()

        # 选中的文件列表
        self.selected_files = []
        self.output_folder = ""

        # 设置样式
        self.setup_styles()

        # 创建界面
        self.create_widgets()

        # 启用拖放
        self.setup_drag_drop()

    def setup_styles(self):
        """设置界面样式"""
        style = ttk.Style()
        style.theme_use('clam')

        # 配置颜色
        style.configure('TFrame', background='#f0f0f0')
        style.configure('TLabel', background='#f0f0f0', font=('微软雅黑', 10))
        style.configure('Title.TLabel', font=('微软雅黑', 14, 'bold'))
        style.configure('TButton', font=('微软雅黑', 9))
        style.configure('TNotebook', background='#f0f0f0')
        style.configure('TNotebook.Tab', font=('微软雅黑', 10))

    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)

        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="文件", menu=file_menu)
        file_menu.add_command(label="添加文件", command=self.add_files, accelerator="Ctrl+O")
        file_menu.add_command(label="清空列表", command=self.clear_files, accelerator="Ctrl+L")
        file_menu.add_command(label="选择输出文件夹", command=self.select_output_folder, accelerator="Ctrl+S")
        file_menu.add_separator()
        file_menu.add_command(label="退出", command=self.root.quit, accelerator="Ctrl+Q")

        # 工具菜单
        tools_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="工具", menu=tools_menu)
        tools_menu.add_command(label="打开输出文件夹", command=self.open_output_folder)
        tools_menu.add_separator()
        tools_menu.add_command(label="清空文件列表", command=self.clear_files)

        # 帮助菜单
        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="使用说明", command=self.show_help, accelerator="F1")
        help_menu.add_command(label="快速入门", command=self.show_quick_start)
        help_menu.add_command(label="常见问题", command=self.show_faq)
        help_menu.add_separator()
        help_menu.add_command(label="关于", command=self.show_about)

        # 绑定快捷键
        self.root.bind('<Control-o>', lambda e: self.add_files())
        self.root.bind('<Control-l>', lambda e: self.clear_files())
        self.root.bind('<Control-s>', lambda e: self.select_output_folder())
        self.root.bind('<Control-q>', lambda e: self.root.quit())
        self.root.bind('<F1>', lambda e: self.show_help())

    def create_toolbar(self):
        """创建工具栏"""
        toolbar = ttk.Frame(self.root)
        toolbar.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=5, pady=5)

        # 快速操作按钮
        ttk.Button(toolbar, text="📁 添加文件", command=self.add_files, width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="🗑️ 清空列表", command=self.clear_files, width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="📂 输出文件夹", command=self.select_output_folder, width=14).pack(side=tk.LEFT, padx=2)

        # 分隔符
        ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=5)

        # 帮助按钮
        ttk.Button(toolbar, text="❓ 使用说明", command=self.show_help, width=12).pack(side=tk.LEFT, padx=2)

    def show_help(self):
        """显示使用说明"""
        help_text = """
文件格式转换工具箱 v3.0.1 - 使用说明

【基本操作】
1. 点击"添加文件"或使用快捷键 Ctrl+O 选择要转换的文件
2. 在上方选项卡中选择对应的转换类型
3. 点击转换按钮开始转换
4. 转换完成后可选择打开输出文件夹

【支持的格式】
📄 文档格式：PDF、Word、Markdown、HTML
📊 数据表格：Excel、CSV、JSON、ODS
🖼️ 图片格式：PNG、JPG、BMP、WebP、SVG
📦 压缩格式：ZIP、RAR
📝 文本编码：UTF-8、GBK（支持自动检测）

【特色功能】
• Markdown ↔ HTML/Word - 技术文档发布
• JSON ↔ Excel/CSV - API数据处理
• WebP格式 - 现代Web图片优化
• SVG矢量图 - 图标处理
• 自动编码检测 - 解决中文乱码

【快捷键】
Ctrl+O - 添加文件
Ctrl+L - 清空列表
Ctrl+S - 选择输出文件夹
F1 - 显示帮助

【注意事项】
• 部分功能需要安装额外依赖，详见 requirements.txt
• 建议先指定输出文件夹，避免覆盖原文件
• 批量转换时会依次处理所有文件

更多信息请查看 README.md 文档
        """
        self.show_message_dialog("使用说明", help_text, width=600, height=500)

    def show_quick_start(self):
        """显示快速入门"""
        quick_start_text = """
快速入门指南

【第一次使用】
1️⃣ 安装基础依赖
   pip install -r requirements.txt

2️⃣ 选择文件并转换
   文件 → 添加文件 → 选择转换类型

【常用场景示例】

📝 Markdown转HTML（技术文档发布）
   1. 准备 .md 文件
   2. 选择"文档格式"选项卡
   3. 点击"MD → HTML"
   4. 生成带样式的网页

📊 Excel转JSON（API数据）
   1. 准备 .xlsx 文件
   2. 选择"数据表格"选项卡
   3. 点击"Excel → JSON"
   4. 生成JSON格式数据

🖼️ 图片转WebP（Web优化）
   1. 准备图片文件（PNG/JPG）
   2. 选择"图片格式"选项卡
   3. 点击"PNG → WebP"
   4. 文件大小减少30-50%

📝 编码转换（解决乱码）
   1. 准备文本文件
   2. 选择"压缩与编码"选项卡
   3. 点击"自动 → UTF-8"
   4. 自动检测并转换编码

【推荐工作流程】
1. 创建专门的输出文件夹
2. 批量添加同类型文件
3. 执行转换
4. 检查输出结果

需要更多帮助？请查看"帮助 → 常见问题"
        """
        self.show_message_dialog("快速入门", quick_start_text, width=600, height=500)

    def show_faq(self):
        """显示常见问题"""
        faq_text = """
常见问题解答

Q1: 转换失败怎么办？
A1: 首先检查：
   • 文件格式是否正确
   • 是否安装了对应的依赖库（参考 requirements.txt）
   • 文件是否损坏或被占用
   • 查看错误提示信息

Q2: 如何提高转换质量？
A2: 建议安装推荐依赖：
   • PDF转换：pip install PyMuPDF pdfplumber
   • Markdown：pip install pypandoc（需安装pandoc工具）
   • SVG转换：pip install cairosvg
   • 压缩格式：安装WinRAR或pip install rarfile

Q3: Markdown转Word质量不佳？
A3: 安装pandoc获得最佳质量：
   1. 下载：https://pandoc.org/installing.html
   2. pip install pypandoc
   3. 重新转换

Q4: SVG转PNG失败？
A4: 尝试安装以下库之一：
   pip install cairosvg（推荐）
   pip install svglib
   pip install wand（需安装ImageMagick）

Q5: RAR转ZIP失败？
A5: 需要：
   • 方案1：安装WinRAR（https://www.rarlab.com/）
   • 方案2：pip install rarfile
   • Linux：sudo apt-get install unrar

Q6: 编码检测不准确？
A6: 建议：
   1. 确认已安装：pip install chardet
   2. 尝试手动指定编码（GBK → UTF-8）
   3. 检查文件BOM标记

Q7: 支持批量转换吗？
A7: 是的！一次添加多个文件，程序会自动依次处理。

Q8: 输出文件在哪里？
A8: 如果未指定输出文件夹，输出文件会保存在源文件所在的文件夹。

Q9: 如何卸载程序？
A9: 删除程序文件夹即可，无需额外操作。

Q10: 是否支持命令行？
A10: 目前仅支持GUI界面，命令行版本正在开发中。

更多问题？请联系 508125305@qq.com
        """
        self.show_message_dialog("常见问题", faq_text, width=650, height=550)

    def show_about(self):
        """显示关于信息"""
        about_text = """
文件格式转换工具箱
File Format Converter Toolbox

版本：v3.0.1
更新日期：2025-01

【功能特性】
✓ 文档转换：PDF、Word、Markdown、HTML
✓ 数据处理：Excel、CSV、JSON、ODS
✓ 图片转换：PNG、JPG、WebP、SVG、BMP
✓ 压缩格式：ZIP、RAR互转
✓ 编码转换：UTF-8、GBK（自动检测）

【技术栈】
• Python 3.8+
• tkinter GUI
• 22种转换功能
• 多层降级策略确保成功率

【新版本特性 v3.0】
✨ Markdown文档转换（HTML、Word）
✨ JSON数据格式支持
✨ WebP现代图片格式
✨ SVG矢量图处理
✨ 文本编码自动检测

【版权信息】
本软件免费开源，仅供学习交流使用
遵循MIT开源协议

【感谢使用】
如有问题或建议，欢迎反馈！

项目主页：https://gitee.com/fiagainster/format-conversion-tool-set
文档：README.md
        """
        self.show_message_dialog("关于", about_text, width=500, height=550)

    def open_output_folder(self):
        """打开输出文件夹"""
        if not self.output_folder:
            messagebox.showwarning("提示", "尚未指定输出文件夹！\n\n请先选择输出文件夹。")
            return

        if os.path.exists(self.output_folder):
            os.startfile(self.output_folder)
        else:
            messagebox.showerror("错误", f"文件夹不存在：\n{self.output_folder}")

    def show_message_dialog(self, title, message, width=500, height=400, font=None):
        """显示消息对话框
        :param title: 标题
        :param message: 消息内容
        :param width: 窗口宽度
        :param height: 窗口高度
        :param font: 字体设置
        """
        dialog = tk.Toplevel(self.root)
        dialog.title(title)
        dialog.geometry(f"{width}x{height}")
        dialog.resizable(True, True)

        # 文本框
        text_frame = ttk.Frame(dialog, padding="10")
        text_frame.pack(fill=tk.BOTH, expand=True)

        # 使用Text控件显示内容
        text_widget = tk.Text(text_frame, wrap=tk.WORD, font=font or ('微软雅黑', 10))
        text_widget.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 滚动条
        scrollbar = ttk.Scrollbar(text_frame, orient=tk.VERTICAL, command=text_widget.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        text_widget.config(yscrollcommand=scrollbar.set)

        # 插入内容
        text_widget.insert(1.0, message)
        text_widget.config(state=tk.DISABLED)

        # 关闭按钮
        btn_frame = ttk.Frame(dialog, padding="10")
        btn_frame.pack(fill=tk.X)
        ttk.Button(btn_frame, text="关闭", command=dialog.destroy).pack(side=tk.RIGHT)

        # 居中显示
        dialog.transient(self.root)
        dialog.grab_set()

    def create_widgets(self):
        """创建界面组件"""
        # 创建菜单栏
        self.create_menu_bar()

        # 创建工具栏
        self.create_toolbar()

        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 标题
        title_label = ttk.Label(main_frame, text="文件格式转换工具箱", style='Title.TLabel')
        title_label.grid(row=0, column=0, columnspan=2, pady=10)

        # 创建选项卡
        self.notebook = ttk.Notebook(main_frame)
        self.notebook.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=10)

        # 文档转换选项卡
        self.create_document_tab()

        # 表格转换选项卡
        self.create_spreadsheet_tab()

        # 图片转换选项卡
        self.create_image_tab()

        # 压缩与编码选项卡
        self.create_archive_encoding_tab()

        # 其他转换选项卡
        self.create_other_tab()

        # 文件列表区域
        list_frame = ttk.LabelFrame(main_frame, text="选中的文件", padding="10")
        list_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=10)

        # 文件列表
        self.file_listbox = tk.Listbox(list_frame, height=6, selectmode=tk.EXTENDED)
        self.file_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.file_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.file_listbox.config(yscrollcommand=scrollbar.set)

        # 文件操作按钮
        btn_frame = ttk.Frame(main_frame)
        btn_frame.grid(row=3, column=0, columnspan=2, pady=10)

        ttk.Button(btn_frame, text="添加文件", command=self.add_files).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="清空列表", command=self.clear_files).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="选择输出文件夹", command=self.select_output_folder).pack(side=tk.LEFT, padx=5)

        # 输出文件夹显示
        self.output_label = ttk.Label(main_frame, text="输出文件夹: 未选择（默认为源文件所在文件夹）")
        self.output_label.grid(row=4, column=0, columnspan=2, pady=5)

        # 进度条（带框架以增加可见性）
        progress_frame = ttk.LabelFrame(main_frame, text="转换进度", padding="5")
        progress_frame.grid(row=5, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)

        self.progress = ttk.Progressbar(progress_frame, mode='determinate', maximum=100, length=400)
        self.progress.pack(fill=tk.X, expand=True, padx=5, pady=5)

        # 状态标签
        self.status_label = ttk.Label(main_frame, text="就绪")
        self.status_label.grid(row=6, column=0, columnspan=2, pady=5)

        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(1, weight=1)  # 让main_frame可以扩展
        main_frame.columnconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(1, weight=0)  # 选项卡不扩展
        main_frame.rowconfigure(2, weight=1)  # 文件列表可扩展

    def create_document_tab(self):
        """创建文档转换选项卡"""
        doc_frame = ttk.Frame(self.notebook, padding="10")
        self.notebook.add(doc_frame, text="文档格式")

        # PDF与Word互转
        pdf_word_frame = ttk.LabelFrame(doc_frame, text="PDF与Word互转", padding="10")
        pdf_word_frame.pack(fill=tk.X, pady=5)

        ttk.Button(pdf_word_frame, text="PDF → Word",
                   command=lambda: self.convert_files('pdf_to_word')).pack(side=tk.LEFT, padx=5)
        ttk.Button(pdf_word_frame, text="Word → PDF",
                   command=lambda: self.convert_files('word_to_pdf')).pack(side=tk.LEFT, padx=5)

        # PDF与图片互转
        pdf_img_frame = ttk.LabelFrame(doc_frame, text="PDF与图片互转", padding="10")
        pdf_img_frame.pack(fill=tk.X, pady=5)

        ttk.Button(pdf_img_frame, text="PDF → 图片",
                   command=lambda: self.convert_files('pdf_to_images')).pack(side=tk.LEFT, padx=5)
        ttk.Button(pdf_img_frame, text="图片 → PDF",
                   command=lambda: self.convert_files('images_to_pdf')).pack(side=tk.LEFT, padx=5)

        # Markdown转换（新增）
        md_frame = ttk.LabelFrame(doc_frame, text="Markdown转换", padding="10")
        md_frame.pack(fill=tk.X, pady=5)

        ttk.Button(md_frame, text="MD → HTML",
                   command=lambda: self.convert_files('md_to_html')).pack(side=tk.LEFT, padx=5)
        ttk.Button(md_frame, text="MD → Word",
                   command=lambda: self.convert_files('md_to_word')).pack(side=tk.LEFT, padx=5)
        ttk.Button(md_frame, text="HTML → MD",
                   command=lambda: self.convert_files('html_to_md')).pack(side=tk.LEFT, padx=5)
        ttk.Button(md_frame, text="Word → MD",
                   command=lambda: self.convert_files('word_to_md')).pack(side=tk.LEFT, padx=5)

        # Word版本转换
        word_frame = ttk.LabelFrame(doc_frame, text="Word版本转换", padding="10")
        word_frame.pack(fill=tk.X, pady=5)

        ttk.Button(word_frame, text="DOC → DOCX",
                   command=lambda: self.convert_files('doc_to_docx')).pack(side=tk.LEFT, padx=5)
        ttk.Button(word_frame, text="DOCX → DOC",
                   command=lambda: self.convert_files('docx_to_doc')).pack(side=tk.LEFT, padx=5)

    def create_spreadsheet_tab(self):
        """创建表格转换选项卡"""
        sheet_frame = ttk.Frame(self.notebook, padding="10")
        self.notebook.add(sheet_frame, text="数据表格")

        # Excel版本转换
        excel_frame = ttk.LabelFrame(sheet_frame, text="Excel版本转换", padding="10")
        excel_frame.pack(fill=tk.X, pady=5)

        ttk.Button(excel_frame, text="XLS → XLSX",
                   command=lambda: self.convert_files('xls_to_xlsx')).pack(side=tk.LEFT, padx=5)
        ttk.Button(excel_frame, text="XLSX → XLS",
                   command=lambda: self.convert_files('xlsx_to_xls')).pack(side=tk.LEFT, padx=5)

        # Excel与CSV互转
        csv_frame = ttk.LabelFrame(sheet_frame, text="Excel与CSV互转", padding="10")
        csv_frame.pack(fill=tk.X, pady=5)

        ttk.Button(csv_frame, text="Excel → CSV",
                   command=lambda: self.convert_files('excel_to_csv')).pack(side=tk.LEFT, padx=5)
        ttk.Button(csv_frame, text="CSV → Excel",
                   command=lambda: self.convert_files('csv_to_excel')).pack(side=tk.LEFT, padx=5)

        # JSON数据格式（新增）
        json_frame = ttk.LabelFrame(sheet_frame, text="JSON数据格式", padding="10")
        json_frame.pack(fill=tk.X, pady=5)

        ttk.Button(json_frame, text="Excel → JSON",
                   command=lambda: self.convert_files('excel_to_json')).pack(side=tk.LEFT, padx=5)
        ttk.Button(json_frame, text="JSON → Excel",
                   command=lambda: self.convert_files('json_to_excel')).pack(side=tk.LEFT, padx=5)
        ttk.Button(json_frame, text="CSV → JSON",
                   command=lambda: self.convert_files('csv_to_json')).pack(side=tk.LEFT, padx=5)
        ttk.Button(json_frame, text="JSON → CSV",
                   command=lambda: self.convert_files('json_to_csv')).pack(side=tk.LEFT, padx=5)

        # OpenDocument格式（新增）
        ods_frame = ttk.LabelFrame(sheet_frame, text="OpenDocument表格", padding="10")
        ods_frame.pack(fill=tk.X, pady=5)

        ttk.Button(ods_frame, text="ODS → Excel",
                   command=lambda: self.convert_files('ods_to_excel')).pack(side=tk.LEFT, padx=5)
        ttk.Button(ods_frame, text="Excel → ODS",
                   command=lambda: self.convert_files('excel_to_ods')).pack(side=tk.LEFT, padx=5)

        # 表格转PDF
        pdf_frame = ttk.LabelFrame(sheet_frame, text="表格转PDF", padding="10")
        pdf_frame.pack(fill=tk.X, pady=5)

        ttk.Button(pdf_frame, text="Excel → PDF",
                   command=lambda: self.convert_files('excel_to_pdf')).pack(side=tk.LEFT, padx=5)

    def create_image_tab(self):
        """创建图片转换选项卡"""
        img_frame = ttk.Frame(self.notebook, padding="10")
        self.notebook.add(img_frame, text="图片格式")

        # 图片格式互转
        format_frame = ttk.LabelFrame(img_frame, text="常用格式互转", padding="10")
        format_frame.pack(fill=tk.X, pady=5)

        ttk.Button(format_frame, text="PNG → JPG",
                   command=lambda: self.convert_files('png_to_jpg')).pack(side=tk.LEFT, padx=5)
        ttk.Button(format_frame, text="JPG → PNG",
                   command=lambda: self.convert_files('jpg_to_png')).pack(side=tk.LEFT, padx=5)
        ttk.Button(format_frame, text="BMP → JPG",
                   command=lambda: self.convert_files('bmp_to_jpg')).pack(side=tk.LEFT, padx=5)

        # WebP格式（新增）
        webp_frame = ttk.LabelFrame(img_frame, text="WebP格式（现代Web）", padding="10")
        webp_frame.pack(fill=tk.X, pady=5)

        ttk.Button(webp_frame, text="WebP → PNG",
                   command=lambda: self.convert_files('webp_to_png')).pack(side=tk.LEFT, padx=5)
        ttk.Button(webp_frame, text="WebP → JPG",
                   command=lambda: self.convert_files('webp_to_jpg')).pack(side=tk.LEFT, padx=5)
        ttk.Button(webp_frame, text="PNG → WebP",
                   command=lambda: self.convert_files('png_to_webp')).pack(side=tk.LEFT, padx=5)
        ttk.Button(webp_frame, text="JPG → WebP",
                   command=lambda: self.convert_files('jpg_to_webp')).pack(side=tk.LEFT, padx=5)

        # SVG矢量图（新增）
        svg_frame = ttk.LabelFrame(img_frame, text="SVG矢量图", padding="10")
        svg_frame.pack(fill=tk.X, pady=5)

        ttk.Button(svg_frame, text="SVG → PNG",
                   command=lambda: self.convert_files('svg_to_png')).pack(side=tk.LEFT, padx=5)
        ttk.Button(svg_frame, text="PNG → SVG",
                   command=lambda: self.convert_files('png_to_svg')).pack(side=tk.LEFT, padx=5)

        # 图片转PDF
        pdf_frame = ttk.LabelFrame(img_frame, text="图片转PDF", padding="10")
        pdf_frame.pack(fill=tk.X, pady=5)

        ttk.Button(pdf_frame, text="单图 → PDF",
                   command=lambda: self.convert_files('image_to_pdf')).pack(side=tk.LEFT, padx=5)
        ttk.Button(pdf_frame, text="多图 → PDF",
                   command=lambda: self.convert_files('images_to_pdf')).pack(side=tk.LEFT, padx=5)

    def create_archive_encoding_tab(self):
        """创建压缩与编码转换选项卡"""
        ae_frame = ttk.Frame(self.notebook, padding="10")
        self.notebook.add(ae_frame, text="压缩与编码")

        # 压缩格式转换
        archive_frame = ttk.LabelFrame(ae_frame, text="压缩格式转换", padding="10")
        archive_frame.pack(fill=tk.X, pady=5)

        ttk.Button(archive_frame, text="ZIP → RAR",
                   command=lambda: self.convert_files('zip_to_rar')).pack(side=tk.LEFT, padx=5)
        ttk.Button(archive_frame, text="RAR → ZIP",
                   command=lambda: self.convert_files('rar_to_zip')).pack(side=tk.LEFT, padx=5)

        # 文本编码转换
        encoding_frame = ttk.LabelFrame(ae_frame, text="文本编码转换", padding="10")
        encoding_frame.pack(fill=tk.X, pady=5)

        ttk.Button(encoding_frame, text="GBK → UTF-8",
                   command=lambda: self.convert_files('gbk_to_utf8')).pack(side=tk.LEFT, padx=5)
        ttk.Button(encoding_frame, text="UTF-8 → GBK",
                   command=lambda: self.convert_files('utf8_to_gbk')).pack(side=tk.LEFT, padx=5)

        # 自动检测编码
        auto_encoding_frame = ttk.LabelFrame(ae_frame, text="自动检测编码", padding="10")
        auto_encoding_frame.pack(fill=tk.X, pady=5)

        ttk.Button(auto_encoding_frame, text="自动 → UTF-8",
                   command=lambda: self.convert_files('auto_to_utf8')).pack(side=tk.LEFT, padx=5)
        ttk.Button(auto_encoding_frame, text="自动 → GBK",
                   command=lambda: self.convert_files('auto_to_gbk')).pack(side=tk.LEFT, padx=5)

    def create_other_tab(self):
        """创建其他转换选项卡"""
        other_frame = ttk.Frame(self.notebook, padding="10")
        self.notebook.add(other_frame, text="其他工具")

        # 网页转PDF
        web_frame = ttk.LabelFrame(other_frame, text="网页转PDF", padding="10")
        web_frame.pack(fill=tk.X, pady=5)

        ttk.Label(web_frame, text="输入网址:").pack(side=tk.LEFT, padx=5)
        self.url_entry = ttk.Entry(web_frame, width=40)
        self.url_entry.pack(side=tk.LEFT, padx=5)
        ttk.Button(web_frame, text="转换为PDF",
                   command=self.convert_url_to_pdf).pack(side=tk.LEFT, padx=5)

        # 文档转TXT
        txt_frame = ttk.LabelFrame(other_frame, text="任意文档转TXT", padding="10")
        txt_frame.pack(fill=tk.X, pady=5)

        ttk.Button(txt_frame, text="文档 → TXT",
                   command=lambda: self.convert_files('doc_to_txt')).pack(side=tk.LEFT, padx=5)

    def setup_drag_drop(self):
        """设置拖放功能"""
        # Windows 拖放支持
        try:
            from tkinterdnd2 import DND_FILES, TkinterDnD
            # 如果已经初始化了，重新绑定
            self.file_listbox.drop_target_register(DND_FILES)
            self.file_listbox.dnd_bind('<<Drop>>', self.drop_files)
        except ImportError:
            # 如果没有 tkinterdnd2，就跳过拖放功能
            pass

    def drop_files(self, event):
        """处理拖放的文件"""
        files = self.root.tk.splitlist(event.data)
        for file in files:
            if os.path.isfile(file) and file not in self.selected_files:
                self.selected_files.append(file)
                self.file_listbox.insert(tk.END, os.path.basename(file))

    def add_files(self):
        """添加文件"""
        files = filedialog.askopenfilenames(
            title="选择文件",
            filetypes=[
                ("所有文件", "*.*"),
                ("PDF文件", "*.pdf"),
                ("Word文件", "*.doc *.docx"),
                ("Excel文件", "*.xls *.xlsx"),
                ("图片文件", "*.png *.jpg *.jpeg *.bmp"),
                ("CSV文件", "*.csv")
            ]
        )
        for file in files:
            if file not in self.selected_files:
                self.selected_files.append(file)
                self.file_listbox.insert(tk.END, os.path.basename(file))

    def clear_files(self):
        """清空文件列表"""
        self.selected_files.clear()
        self.file_listbox.delete(0, tk.END)

    def select_output_folder(self):
        """选择输出文件夹"""
        folder = filedialog.askdirectory(title="选择输出文件夹")
        if folder:
            self.output_folder = folder
            self.output_label.config(text=f"输出文件夹: {folder}")

    def convert_url_to_pdf(self):
        """将URL转换为PDF"""
        url = self.url_entry.get().strip()
        if not url:
            messagebox.showwarning("警告", "请输入网址！")
            return

        output_folder = self.output_folder or os.path.expanduser("~/Desktop")

        def convert():
            try:
                self.update_status("正在转换网页...")
                self.progress['value'] = 50
                self.root.update_idletasks()

                result = self.other_converter.url_to_pdf(url, output_folder)

                self.progress['value'] = 100
                self.update_status("转换完成！")

                if messagebox.askyesno("成功", f"网页已转换为PDF！\n是否打开输出文件夹？"):
                    os.startfile(output_folder)

                self.progress['value'] = 0
            except Exception as e:
                self.progress['value'] = 0
                self.update_status("转换失败！")
                messagebox.showerror("错误", f"转换失败：{str(e)}")

        threading.Thread(target=convert, daemon=True).start()

    def validate_file_format(self, file_path, conversion_type):
        """
        验证文件格式是否与转换类型匹配
        :param file_path: 文件路径
        :param conversion_type: 转换类型
        :return: (是否有效, 错误消息)
        """
        ext = os.path.splitext(file_path)[1].lower()
        filename = os.path.basename(file_path)

        # 定义每种转换类型所需的文件格式
        format_requirements = {
            # 文档转换
            'pdf_to_word': ['.pdf'],
            'word_to_pdf': ['.doc', '.docx'],
            'pdf_to_images': ['.pdf'],
            'doc_to_docx': ['.doc'],
            'docx_to_doc': ['.docx'],
            'doc_to_txt': ['.pdf', '.doc', '.docx', '.txt'],

            # Markdown转换
            'md_to_html': ['.md', '.markdown'],
            'md_to_word': ['.md', '.markdown'],
            'html_to_md': ['.html', '.htm'],
            'word_to_md': ['.doc', '.docx'],

            # 表格转换
            'xls_to_xlsx': ['.xls'],
            'xlsx_to_xls': ['.xlsx'],
            'excel_to_csv': ['.xls', '.xlsx'],
            'csv_to_excel': ['.csv'],
            'excel_to_pdf': ['.xls', '.xlsx'],

            # JSON转换
            'excel_to_json': ['.xls', '.xlsx'],
            'json_to_excel': ['.json'],
            'csv_to_json': ['.csv'],
            'json_to_csv': ['.json'],

            # ODS转换
            'ods_to_excel': ['.ods'],
            'excel_to_ods': ['.xls', '.xlsx'],

            # 基础图片转换
            'png_to_jpg': ['.png'],
            'jpg_to_png': ['.jpg', '.jpeg'],
            'bmp_to_jpg': ['.bmp'],
            'image_to_pdf': ['.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff'],
            'images_to_pdf': ['.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff'],

            # WebP转换
            'webp_to_png': ['.webp'],
            'webp_to_jpg': ['.webp'],
            'png_to_webp': ['.png'],
            'jpg_to_webp': ['.jpg', '.jpeg'],

            # SVG转换
            'svg_to_png': ['.svg'],
            'png_to_svg': ['.png'],

            # 压缩格式转换
            'zip_to_rar': ['.zip'],
            'rar_to_zip': ['.rar'],

            # 编码转换（支持所有文本文件）
            'gbk_to_utf8': ['.txt', '.py', '.java', '.cpp', '.c', '.h', '.js', '.html', '.css', '.xml', '.json', '.md', '.csv', '.sql', '.sh', '.bat'],
            'utf8_to_gbk': ['.txt', '.py', '.java', '.cpp', '.c', '.h', '.js', '.html', '.css', '.xml', '.json', '.md', '.csv', '.sql', '.sh', '.bat'],
            'auto_to_utf8': ['.txt', '.py', '.java', '.cpp', '.c', '.h', '.js', '.html', '.css', '.xml', '.json', '.md', '.csv', '.sql', '.sh', '.bat'],
            'auto_to_gbk': ['.txt', '.py', '.java', '.cpp', '.c', '.h', '.js', '.html', '.css', '.xml', '.json', '.md', '.csv', '.sql', '.sh', '.bat'],
        }

        required_formats = format_requirements.get(conversion_type, [])

        if ext not in required_formats:
            format_list = '、'.join(required_formats)
            return False, f"文件 '{filename}' 格式不匹配！\n需要：{format_list}\n实际：{ext}"

        return True, ""

    def convert_files(self, conversion_type):
        """转换文件"""
        if not self.selected_files:
            messagebox.showwarning("警告", "请先添加文件！")
            return

        # 验证所有文件格式
        invalid_files = []
        for file_path in self.selected_files:
            is_valid, error_msg = self.validate_file_format(file_path, conversion_type)
            if not is_valid:
                invalid_files.append(error_msg)

        if invalid_files:
            error_message = "以下文件格式不匹配：\n\n" + "\n\n".join(invalid_files[:5])
            if len(invalid_files) > 5:
                error_message += f"\n\n还有 {len(invalid_files) - 5} 个文件格式不匹配..."
            messagebox.showerror("格式错误", error_message)
            return

        def convert():
            try:
                total_files = len(self.selected_files)
                self.update_status(f"准备转换 {total_files} 个文件...")
                self.progress['value'] = 0
                self.root.update_idletasks()

                success_count = 0
                fail_count = 0
                error_messages = []

                for index, file_path in enumerate(self.selected_files, 1):
                    try:
                        # 更新进度
                        file_name = os.path.basename(file_path)
                        self.update_status(f"正在转换 ({index}/{total_files}): {file_name}")

                        # 确定输出文件夹
                        if self.output_folder:
                            output_dir = self.output_folder
                        else:
                            output_dir = os.path.dirname(file_path)

                        # 根据转换类型调用相应的转换器
                        if conversion_type in ['pdf_to_word', 'word_to_pdf', 'pdf_to_images',
                                                'doc_to_docx', 'docx_to_doc']:
                            result = self.doc_converter.convert(file_path, output_dir, conversion_type)

                        elif conversion_type in ['md_to_html', 'md_to_word', 'html_to_md', 'word_to_md']:
                            result = self.md_converter.convert(file_path, output_dir, conversion_type)

                        elif conversion_type in ['xls_to_xlsx', 'xlsx_to_xls', 'excel_to_csv',
                                                  'csv_to_excel', 'excel_to_pdf', 'excel_to_json',
                                                  'json_to_excel', 'csv_to_json', 'json_to_csv',
                                                  'ods_to_excel', 'excel_to_ods']:
                            result = self.sheet_converter.convert(file_path, output_dir, conversion_type)

                        elif conversion_type in ['png_to_jpg', 'jpg_to_png', 'bmp_to_jpg',
                                                  'image_to_pdf', 'images_to_pdf', 'webp_to_png',
                                                  'webp_to_jpg', 'png_to_webp', 'jpg_to_webp',
                                                  'svg_to_png', 'png_to_svg']:
                            if conversion_type == 'images_to_pdf':
                                # 多图合并为PDF
                                output_dir = self.output_folder or os.path.dirname(self.selected_files[0])
                                result = self.img_converter.images_to_pdf(self.selected_files, output_dir)
                                success_count = 1
                                break
                            else:
                                result = self.img_converter.convert(file_path, output_dir, conversion_type)

                        elif conversion_type in ['zip_to_rar', 'rar_to_zip']:
                            result = self.archive_converter.convert(file_path, output_dir, conversion_type)

                        elif conversion_type in ['gbk_to_utf8', 'utf8_to_gbk', 'auto_to_utf8', 'auto_to_gbk']:
                            result = self.encoding_converter.convert(file_path, output_dir, conversion_type)

                        elif conversion_type == 'doc_to_txt':
                            result = self.other_converter.doc_to_txt(file_path, output_dir)

                        success_count += 1
                        # 更新进度条
                        progress_value = (index / total_files) * 100
                        self.progress['value'] = progress_value
                        self.root.update_idletasks()

                    except Exception as e:
                        error_msg = f"{os.path.basename(file_path)}: {str(e)}"
                        print(f"转换失败 - {error_msg}")
                        error_messages.append(error_msg)
                        fail_count += 1
                        # 即使失败也更新进度
                        progress_value = (index / total_files) * 100
                        self.progress['value'] = progress_value
                        self.root.update_idletasks()

                # 完成后设置进度条为100%
                self.progress['value'] = 100
                self.update_status(f"转换完成！成功: {success_count}, 失败: {fail_count}")

                if success_count > 0:
                    output_dir = self.output_folder or os.path.dirname(self.selected_files[0])
                    result_msg = f"转换完成！\n成功: {success_count}\n失败: {fail_count}"

                    if error_messages and len(error_messages) <= 3:
                        result_msg += "\n\n失败原因：\n" + "\n".join(error_messages)
                    elif error_messages:
                        result_msg += f"\n\n部分文件转换失败，详情请查看控制台"

                    result_msg += "\n\n是否打开输出文件夹？"

                    if messagebox.askyesno("完成", result_msg):
                        os.startfile(output_dir)
                else:
                    error_detail = "\n".join(error_messages[:3])
                    messagebox.showerror("错误", f"所有文件转换失败！\n\n{error_detail}")

            except Exception as e:
                self.progress['value'] = 0
                self.update_status("转换失败！")
                messagebox.showerror("错误", f"转换过程出错：{str(e)}")

        threading.Thread(target=convert, daemon=True).start()

    def update_status(self, message):
        """更新状态标签"""
        self.status_label.config(text=message)
        self.root.update_idletasks()


def main():
    """主函数"""
    try:
        # 尝试使用 tkinterdnd2 支持拖放
        from tkinterdnd2 import TkinterDnD
        root = TkinterDnD.Tk()
    except ImportError:
        # 如果没有安装 tkinterdnd2，使用普通 Tk
        root = tk.Tk()

    app = FileConverterApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()
